﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;

namespace Flagwind.Data
{
	internal class DataParameterFormat : IFormatProvider, ICustomFormatter
	{
		#region 私有字段

		private readonly IList<IDataParameter> _parameters;
		private readonly IDataProvider _dataProvider;
		private int _parameterIndex;

		#endregion

		#region 公共属性

		public IDataParameter[] DataParameters
		{
			get
			{
				return _parameters.ToArray();
			}
		}

		#endregion

		#region 构造方法

		public DataParameterFormat(IDataProvider dataProvider)
		{
			this._dataProvider = dataProvider;
			this._parameters = new List<IDataParameter>();
			this._parameterIndex = 0;
		}

		#endregion

		#region IFormatProvider 成员

		public object GetFormat(Type type)
		{
			if(type == typeof(ICustomFormatter))
			{
				return this;
			}
			else
			{
				return null;
			}
		}

		#endregion

		#region ICustomFormatter 成员

		public string Format(string format, object arg, IFormatProvider formatProvider)
		{
			string paraName = _dataProvider.ParameterChar + "P" + _parameterIndex++;
			if(format == null)
			{
				_parameters.Add(_dataProvider.GetParameter(paraName, arg));
			}
			else
			{
				if(format.IndexOf('.') > 0)
				{
					if(arg != null && arg is decimal)
					{
						//decimal 类型，制定小数位数和精度
						string[] arr = format.Split('.');
						byte precision = 0;
						byte scale = 0;
						if(byte.TryParse(arr[0], out precision) && byte.TryParse(arr[1], out scale))
						{
							IDataParameter para = _dataProvider.GetParameter(paraName, DbType.Decimal, sizeof(decimal), ParameterDirection.Input, precision, scale);
							_parameters.Add(para);
						}
						else
						{
							_parameters.Add(_dataProvider.GetParameter(paraName, arg));
						}
					}
					else
					{
						_parameters.Add(_dataProvider.GetParameter(paraName, arg));
					}
				}
				else
				{
					if(arg != null)
					{
						if(arg is string)
						{
							//字符串类型，制定参数的长度 
							int size = 0;
							if(int.TryParse(format, out size))
							{
								IDataParameter para = _dataProvider.GetParameter(paraName, DbType.String, size);
								para.Value = arg;
								_parameters.Add(para);
							}
							else
							{
								_parameters.Add(_dataProvider.GetParameter(paraName, arg));
							}
						}
						else if(arg is IDataParameter)
						{
							_parameters.Add((IDataParameter)arg);
						}
						else
						{
							_parameters.Add(_dataProvider.GetParameter(paraName, arg));
						}
					}
					else
					{
						_parameters.Add(_dataProvider.GetParameter(paraName, arg));
					}
				}
			}
			return paraName;
		}

		#endregion
	}
}